#!/bin/bash
#################################################
#filename：jdk_version.sh
#功能：获取对应java文件的jdk编译版本
# 如果是jar，这里只会检索jar包中第一个class的jdk编译版本，所以也不一定准确
#
#执行方法：./jdk_version.sh <file_path:[.jar|.class|.war]>
# 1.jar示例：
#  jdk_version.sh xxl-job-admin-2.3.0.jar
# 输出：
#  Build-Jdk: 1.8.0_271
#  file_path:[xxl-job-admin-2.3.0.jar]    major_version:[52] jdk_version:[jdk1.8]

# 2.class示例
#  jdk_version.sh XxlJobAdminConfig.class
# 输出：
#  file_path:[XxlJobAdminConfig.class]   major_version:[52] jdk_version:[jdk1.8]

# 3.war示例
#  jdk_version.sh wardir/BOSS.war
# 输出：
#  file_path:[wardir/BOSS.war]        jdk_version:[1.7.0_67-b01 (Oracle Corporation)]
#################################################

# 定义关联数组
declare -A my_map

# 向关联数组中添加键值对
# LTS:
#    8(2014年初发布，免费版本至8u202，从8u211开始商用收费，支持到2030年9月)
#    11(2018年9月发布，免费版本版本至11.0.2，后续版本商用收费，支持到2032年9月)
#    17(2021年9月发布，免费，支持到2029年9月)
#    21(2023年9月发布，免费，支持到2031年9月)
#    25(预计2025年9月发布，支持到2033年9月)
# 后续Oracle计划每半年发布一个新的大版本(3、9月)，每两年发布一次LTS(9月)，建议正式环境只使用LTS版本
# 此处可以查看jdk发布计划：https://www.java.com/en/releases/matrix/
# JDK下载地址：https://www.oracle.com/cn/java/technologies/downloads/
my_map=(
    [45]="jdk1.1"
    [46]="jdk1.2"
    [47]="jdk1.3"
    [48]="jdk1.4"
    [49]="jdk1.5"
    [50]="jdk1.6"
    [51]="jdk1.7"
    [52]="jdk1.8"
    [53]="jdk9"
    [54]="jdk10"
    [55]="jdk11"
    [56]="jdk12"
    [57]="jdk13"
    [58]="jdk14"
    [59]="jdk15"
    [60]="jdk16"
    [61]="jdk17"
    [62]="jdk18"
    [63]="jdk19"
    [64]="jdk20"
    [65]="jdk21"
    [66]="jdk22"
    [67]="jdk23"
    [68]="jdk24"
    [69]="jdk25"
)


# 打印map
echo_map() {
    echo -e "\tMAJOR_VERSION\tJDK_VERSION"
    for key in "${!my_map[@]}"; do
        echo -e "\t$key\t\t${my_map[$key]}"
    done
}

error_message() {
    echo "Usage: $0 <file_path:[.jar|.class|.war]>"
    echo_map
    exit 1
}

# 检查是否传递了参数
if [ -z "$1" ]; then
    error_message
fi

file_path=$1

# 检查文件是否存在
if [ ! -e "$file_path" ]; then
    echo "文件不存在:file_path:[${file_path}]"
    error_message
fi

greap_content="major version"

if [[ $file_path == *.class ]]; then
    # 通过javap命令获取class文件的详细信息，grep过滤出包含 “major version” 的行，awk取出其版本号
    key=$(javap -verbose "${file_path}" | grep "${greap_content}" | awk -F': ' '{print $2}')
elif [[ $file_path == *.jar ]]; then
    # 先通过“jar tf”命令获取jar包中的class文件，这里只取出第一个，注意这里class路径必须去掉“.class”，之后再通过javap命令获取“-classpath”所指定的jar中的这个第一个class文件的详细信息，grep过滤出包含 “major version” 的行，awk取出其版本号
    key=$(javap -classpath "${file_path}" -verbose "$(jar tf "${file_path}" | grep ".class$" | head -n 1 | sed s/.class//)" | grep "${greap_content}" | awk -F': ' '{print $2}')
    # 通过jar包中的MANIFEST.MF文件来判断打包的jdk版本
    result=$(unzip -p "${file_path}" $(jar tf "${file_path}" | grep "MANIFEST.MF$" | head -n 1) | grep "^Build-Jdk")
    if [ -z "$result" ]; then
        result=$(unzip -p "${file_path}" $(jar tf "${file_path}" | grep "MANIFEST.MF$" | head -n 1) | grep "^Created-By")
    fi

    if [ -n "$result" ]; then
        echo "$result"
    else
        echo "没有在 MANIFEST.MF 中发现jdk相关信息"
    fi
elif [[ $file_path == *.war ]]; then
    # 查找 Build-Jdk
    jdk_version=$(unzip -p "${file_path}" META-INF/MANIFEST.MF | grep -i "^Build-Jdk" | awk -F': ' '{print $2}')

    # 如果 Build-Jdk 未找到，则尝试查找 Created-By
    if [ -z "$jdk_version" ]; then
        jdk_version=$(unzip -p "${file_path}" META-INF/MANIFEST.MF | grep -i "^Created-By" | awk -F': ' '{print $2}')
    fi
else
    error_message
fi

# 打印结果
# 输出 JDK 版本信息
if [ -n "$key" ]; then
    echo -e "file_path:[${file_path}]\tmajor_version:[$key]\tjdk_version:[${my_map[$key]}]"
elif [ -n "$jdk_version" ]; then
    # jdk_version含有特殊字符，通过如下命令查看包含哪些特殊字符，结果发现包含\r\n
    # echo "${jdk_version}" | od -c
    # 去掉特殊字符 \r\n
    jdk_version_cleaned=$(echo "${jdk_version}" | tr -d '\r\n')

    echo -e "file_path:[${file_path}]\t\tjdk_version:[${jdk_version_cleaned}]"
else
    echo "JDK Version information not found"
fi

